iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 13
0

介紹
Redux 是一個 Global State Management ,提供了一個 Store 的使用所有的State(reducer)都會在這裡 ,而當有些時候需要發Request,前面的Redux篇有介紹使用最基礎的 Thunk 來發Fetch 請求(通常都會稱為 Side Effect), 而Redux-Saga 提供各種 effect 的method 在管理這些 Side Effect的工作

Redux-Saga 的Store設定

以下設定跟 Redux 差不多,這邊的rootSaga 要給設定一個起始路徑,再使用 createSagaMiddleware 建立一個 sagaMiddleware instance 除了在 Reudx 中applyMiddleware ,要再額外指定 saga 的工作路徑 store.sagaTask = sagaMiddleware.run(rootSaga)

import {createStore, applyMiddleware} from 'redux'
import {composeWithDevTools} from 'redux-devtools-extension'
import withRedux from 'next-redux-wrapper'
import nextReduxSaga from 'next-redux-saga'
import createSagaMiddleware from 'redux-saga'

import rootReducer, {exampleInitialState} from './reducer'
import rootSaga from './saga'

const sagaMiddleware = createSagaMiddleware()

export function configureStore (initialState = exampleInitialState) {
  const store = createStore(
    rootReducer,
    initialState,
    composeWithDevTools(applyMiddleware(sagaMiddleware))
  )

  store.sagaTask = sagaMiddleware.run(rootSaga)
  return store
}

export function withReduxSaga (BaseComponent) {
  return withRedux(configureStore)(nextReduxSaga(BaseComponent))
}

在Redux-Saga中 提供了許多effects, 這些effect take類的是監聽, put是發dispatch,call是發 request 以下方的程式碼來介紹

import {all, call, put, take, takeLatest} from 'redux-saga/effects'

每一個 effect都有各自的功能,這邊介紹一些簡單的,還有其他更多effect可以參考 Redux-Saga 官方

all : 可以想像 while迴圈 包住裡面的各種 effect 邏輯,通常根部會有fork支線比較清楚,但也可以沒有
call : 就是 發一個 dispatch payload, 所以在原本的寫在 actions.js 的dispatch就會移到這邊的call來發送 paylad 然後 這邊的takeLatest則監聽發送 actionTypes 這邊保持原本的 actions.js 發 actiontype 但處理的地方以下方為例則改到 loadDataSaga處理

take : 監聽如果有對應的 action.type 就看要執行哪個 method
takeLatest : 如果多發很多筆 action.type 只取最後一個

function * rootSaga () {
  yield all([
    call(runClockSaga),
    takeLatest(actionTypes.LOAD_DATA, loadDataSaga)
  ])
}

在下面可以看到 put ,這裡的 put 就會發dispatch ,而可以在Saga之中常看見大量使用 yield 而且 function 都會加上*這裡是使用 Es6 generator ,一般可以理解成迴圈中執行某些 Event 完就到外層看看有沒有要在做什麼,如果沒有的話就回到原來的迴圈 繼續做下一步 ,也因此有這個特性所以可以在 Redux-Saga 中做到取消發 fetch 這件事情

    yield put(tickClock(false))

Next.js中要注意的是 import 'isomorphic-unfetch' 這邊使用了後端也可以發fetch功能的套件,還有一個es6promise的polyfill 補丁 ,其他部分跟SPA使用一樣

/* global fetch */

import {delay} from 'redux-saga'
import {all, call, put, take, takeLatest} from 'redux-saga/effects'
import es6promise from 'es6-promise'
import 'isomorphic-unfetch'

import {actionTypes, failure, loadDataSuccess, tickClock} from './actions'

es6promise.polyfill()

function * runClockSaga () {
  yield take(actionTypes.START_CLOCK)
  while (true) {
    yield put(tickClock(false))
    yield call(delay, 800)
  }
}

function * loadDataSaga () {
  try {
    const res = yield fetch('https://jsonplaceholder.typicode.com/users')
    const data = yield res.json()
    yield put(loadDataSuccess(data))
  } catch (err) {
    yield put(failure(err))
  }
}

function * rootSaga () {
  yield all([
    call(runClockSaga),
    takeLatest(actionTypes.LOAD_DATA, loadDataSaga)
  ])
}

export default rootSaga

總結

Redux-Saga 使用了許多 effect 來的做 side effect 的管理,比起thunk 因為有 es6 generator 的特性,增加許多彈性,設定上一般會把原來的 action.js 中發 dispatch的部分換到 Redex-Saga 中的 put去發 ,在 Next.js 設定部分也是要注意到SSR補丁的部分

github

https://github.com/zeit/next.js/tree/canary/examples/with-redux-saga


上一篇
Next.js & ApolloData(三) Query & Mutation
下一篇
Next.js & Webpack-Bundle-Analyzer
系列文
Next.js + 各種套件組合30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言